#! /bin/bash
### BEGIN INIT INFO
# Provides:          lance_tool
# Required-Start:    $network $local_fs
# Required-Stop:     $network $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      1
# Short-Description: Start lance_tool
# Description: Start and Stop the lance_tool
### END INIT INFO
#
# Lance Tool
#
# chkconfig: 345 20 80
# description: Lance Tool
#
# /etc/rc.d/init.d/lance_*
# See how we were called.

XRUN_MODE="" # Can be Server/Client/Agent
AGENT_ADDR="192.168.100.200"

function proc_pid(){
    ps -elf | grep "`basename $0`" | grep background | grep -v grep | awk '{print $4}' | head -n 1
    return 0
}

# The first PPP connection inside system
function ppp_device(){
    ifconfig | grep "ppp" | grep "Point-to-Point" | head -n 1 | awk '{print $1}'
    return 0
}

# Ensure you setup lzxnet agent to use 192.168.100.200 ip addr
# ppp0      Link encap:Point-to-Point Protocol
#           inet addr:192.168.100.2  P-t-P:192.168.100.200  Mask:255.255.255.255
function ppp_dev2agent()
{
    ifconfig | awk -F":" 'BEGIN{ ppp_dev=""; }{\
      if ( $1 ~ /^ppp.*/ && $2 ~ /^Point-to-Point.*/ ){\
        split($1, part, /[ |	]+/);\
        ppp_dev=part[1];\
      }\
      if ( $0 ~ /inet addr:.*P-t-P:.*Mask:/){\
        split($3, ipaddr, /[ |    ]+/);\
        print ppp_dev, ipaddr[1];\
      }\
    }' | grep "$AGENT_ADDR" | awk '{print $1}'
    return 0
}

function ppp_local(){
    ifconfig | grep "P-t-P" | head -n 1 | awk '{print $2}' | awk -F":" '{print $2}'
    return 0
}

function ppp_remote(){
    ifconfig | grep "P-t-P" | head -n 1 | awk '{print $3}' | awk -F":" '{print $2}'
    return 0
}

function print_ppp_conf(){
  PPP_CNF_DIR="/etc/ppp/peers/"

  find "$PPP_CNF_DIR" -type f | \
    grep -v "provider" | \
    awk -F"/" '{print $NF}'
  return 0
}

function print_ppp_dev(){
  ifconfig | \
    grep "ppp" | \
    grep "Point-to-Point" | \
    awk '{print $1}'
  return 0
}

function vpn_conn(){
  print_ppp_conf | while read pppcnf
  do
    nohup /usr/sbin/pppd call "$pppcnf" >/dev/null 2>&1 &
  done

  sleep 5

  if [ $? -eq 0 ]
  then
    return 0
  else
    return 1
  fi
}

function vpn_dscn(){
  print_ppp_dev | while read pppdev
  do
    if [ -r /var/run/$pppdev.pid ]
    then
      kill -INT `cat /var/run/$pppdev.pid`
      if [ !"$?" = "0" ]
      then
        rm -rf /var/run/$pppdev.pid
        # echo "ERROR: Removed stale pid file"
        return 1
      fi
        # echo "PPP link to $PPP_DEV terminated."
      return 0
    fi
  done
  # echo "ERROR: no active PPP links"
  return 1
}

function vpn_stat(){
    PID=`proc_pid`
    PPP_DEV=`ppp_device`
    PPP2AGT=`ppp_dev2agent`

    [ "$PID" != "" ] && echo "`basename $0` Daemon Process [$PID]"
    [ "$PPP_DEV" != "" ] && [ -r /var/run/$PPP_DEV.pid ] && echo "`basename $0` PPTP Process [`cat /var/run/$PPP_DEV.pid`]"
   
    echo "XRUN_MODE: $XRUN_MODE" 
    echo "PPP_DEV:   $PPP_DEV"
    [ "$XRUN_MODE" == "server" ] && echo "PPP2AGT:   $PPP2AGT"
    echo "Local IP:  "`ppp_local`
    echo "Remote IP: "`ppp_remote`
    exit 0
}

function check_ppp(){
    # Interface test
    itf_test=`ppp_device`
    echo "[CK]: itf_test = $itf_test"
    if [ "$itf_test" == "" ]
    then
        echo "[ER]: VPN interface not found ......"
        vpn_dscn
        vpn_conn
        return 1
    fi

    # Remote Addr test
    remote_addr=`ppp_remote`
    echo "[CK]: remote_addr = $remote_addr"
    if [ "$remote_addr" == "" ]
    then
        echo "[ER]: VPN remote address not found ......"
        vpn_dscn
        vpn_conn
        return 1
    fi
  
    # Link Test
    link_test=$(ping -c 3 "$remote_addr" | grep "time=")
    echo "[CK]: link_test = $link_test"
    if [ "$link_test" == "" ]
    then
        echo "[ER]: VPN Gateway is offline ......"
        vpn_dscn
        vpn_conn
        return 1
    fi

    echo "check_ppp finished, ALL OK"
    return 0
}

# Agent is not required to use setup_route
# Server needs to run this script to setup ppp forwading & routing
# Client also need to forward all packet to the first ppp conn
function setup_route(){
    oslo_route=`route | grep "10.0.0.0" | grep "ppp"`
    [ "$oslo_route" != "" ] && return 0

    itf=""
    [ "$XRUN_MODE" == "client" ] && itf=`ppp_device`
    [ "$XRUN_MODE" == "server" ] && itf=`ppp_dev2agent`
    [ "$itf" == "" ] && return 1
    echo "[SR]: PPP_DEV = $itf"

    addr="$AGENT_ADDR"
    [ "$XRUN_MODE" == "client" ] && addr=`ppp_remote`
    [ "$addr" == "" ] && return 1

    rulnum=`iptables -t nat -L POSTROUTING --line-numbers | grep "10.0.0.0" | awk '{print $1}'`
    [ "$rulnum" != "" ] && iptables -t nat -D POSTROUTING "$rulnum"
    iptables -d 10.0.0.0/8 -o "$itf" -t nat -A POSTROUTING -j MASQUERADE
    echo "[SR]: iptables -d 10.0.0.0/8 -o $itf -t nat -A POSTROUTING -j MASQUERADE"

    echo "[SR]: route add -net 10.0.0.0 netmask 255.0.0.0 gw $addr device $itf"
    route del -net 10.0.0.0 netmask 255.0.0.0 1>/dev/null  2>&1
    route add -net 10.0.0.0 netmask 255.0.0.0 gw $addr device $itf
    return
}

case "$1" in
    start)
        nohup $0 background >/dev/null 2>&1 &
        sleep 3
        PID=`proc_pid`
        echo "Started `basename $0` [$PID]"
        exit 0
    ;;

    stop)
        PID=`proc_pid`
        if [ "$PID" != "" ]
        then
            kill -s 9 $PID
            sleep 3
            [ "$XRUN_MODE" == "agent" ] && vpn_dscn
            [ "$XRUN_MODE" == "client" ] && vpn_dscn
            echo "Stopped `basename $0` [$PID]"
        else
            echo "Nothing to do."
        fi
        exit 0
    ;;

    restart)
        $0 stop
        $0 start
        exit 0
    ;;

    test)
        check_ppp 
        exit 0
    ;;

    status)
        PID=`proc_pid`
        PPP_DEV=`ppp_device`
        PPP2AGT=`ppp_dev2agent`

        [ "$PID" != "" ] && echo "`basename $0` Daemon Process [$PID]"
        [ "$PPP_DEV" != "" ] && [ -r /var/run/$PPP_DEV.pid ] && echo "`basename $0` PPTP Process [`cat /var/run/$PPP_DEV.pid`]"

        echo "XRUN_MODE: $XRUN_MODE"
        echo "PPP_DEV:   $PPP_DEV"
        [ "$XRUN_MODE" == "server" ] && echo "PPP2AGT:   $PPP2AGT"
        echo "Local IP:  "`ppp_local`
        echo "Remote IP: "`ppp_remote`
        exit 0
    ;;

    background)
        while [ 1 ]
        do
            [ "$XRUN_MODE" == "agent"  ] && check_ppp
            [ "$XRUN_MODE" == "client" ] && check_ppp && setup_route
            [ "$XRUN_MODE" == "server" ] && setup_route
            sleep 15
        done
        exit 0
    ;;

    install)
        XRUN_MODE="client" # default is client
        [ "$2" == "server" ] && XRUN_MODE="$2"
        [ "$2" == "agent"  ] && XRUN_MODE="$2"
        [ "$2" == "client" ] && XRUN_MODE="$2"

        echo "install `basename $0` as $XRUN_MODE"
        CUR_DIR="`pwd`"
        cd "`dirname $0`"
        cat `basename $0` | awk  '{\
          if ($0 ~ /^XRUN_MODE=.+/){\
            print "XRUN_MODE=\"""'"$XRUN_MODE"'""\"";\
          } else {\
            print $0;\
          }\
        }' > /etc/init.d/`basename $0`
        chmod +x /etc/init.d/`basename $0`
        chkconfig `basename $0` on 2>/dev/null
        chkconfig `basename $0` on 2>/dev/null

        cp ./config/chap-secrets  /etc/ppp/
        cp ./config/pptpd.conf    /etc/
        cp ./config/pptpd-options /etc/ppp/
        cp ./config/options       /etc/ppp/
        cp ./config/Lance_VPN     /etc/ppp/peers/
        cd "$CUR_DIR"

        exit 0
    ;;

    *)
        echo "Usage: /etc/init.d/`basename $0` {start|stop|restart|status}"
        exit 1
    ;;
esac


